package com.wzl.thread.controller;

import com.wzl.common.VkPublicResponse;
import com.wzl.thread.example.TcSeckillShop;
import com.wzl.thread.pool.TcNewCachedThreadPool;
import com.wzl.thread.pool.TcNewFixedThreadPool;
import com.wzl.thread.pool.TcNewScheduledThreadPool;
import com.wzl.thread.pool.TcNewSingleThreadExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.*;

/**
 * 线程池使用
 * @author weizhongli
 * @since 2022-09-19 10:19
 *
 * 第一种：newCachedThreadPool：线程的数据是不做限制的，每次有任务来的时候都会以任务优先，性能最大化（也就是服务器压力比较大）
 * 第二种：newFixedThreadPool：可以让压力不那么大，并且可以规定线程的数量，当线程的数量达到指定数量的时候，这个时候就不会再有新的线程了
 * 第三种：newSingleThreadExecutor：绝对的安全，不考虑性能，因为是单线程，永远只有一个线程来执行任务。
 *
 * ScheduleExecutorService中三个方法的小结:
 * 1、设置延迟多长时间任务执行，可以使用schedule()方法
 * 2、设置每间隔多长时间执行，有两种方式：
 *  方式一：只计算第一次开始到第二次开始的间隔时间  scheduleAtFixedRate()
 *  方式二：第一次任务结束之后开始计时，间隔多长时间，到第二次任务开始之前，这个时间段。  scheduleWithFixedDelay()
 *
 * 关闭线程方法：shutdown和shutdownNow的区别
 * shutdown()：仅仅是不再接受新的任务，以前的任务还会继续执行
 * shutdownNow()：立刻关闭线程池，如果线程池中还有缓存的任务没有执行，则取消执行，并返回这些任务
 */
@RestController
@Slf4j
public class TcThreadPoolController {

    @Qualifier("threadPoolTaskExecutor")
    @Autowired
    private ThreadPoolTaskExecutor executor;

    /**
     * newCachedThreadPool方法测试
     */
    @RequestMapping("/poolTest1")
    public VkPublicResponse poolTest1() throws ExecutionException, InterruptedException {
        Future<?> future = TcNewCachedThreadPool.NoFactoryPool();
        boolean done = future.isDone();
        log.info("第一次判断任务是否完成：" + done);
        boolean cancelled = future.isCancelled();
        log.info("第一次判断任务是否取消：" + cancelled);
        Integer v = (Integer) future.get();//一直等待任务的执行，直到完成
        log.info("任务执行的结果是："  + v);
        //再一次判断任务是否完成
        boolean done2 = future.isDone();
        log.info("第二次判断任务是否完成：" + done2);
        boolean cancelled2 = future.isCancelled();
        log.info("第二次判断任务是否取消：" + cancelled2);

        //TcNewCachedThreadPool.factoryPool();
        return new VkPublicResponse(future);
    }

    /**
     * newFixedThreadPool方法方法测试
     */
    @RequestMapping("/poolTest2")
    public VkPublicResponse poolTest2(){
        //TcFixedThreadPool.NoFactoryPool();
        TcNewFixedThreadPool.factoryPool();
        return new VkPublicResponse();
    }

    /**
     * newSingleThreadExecutor方法方法测试
     */
    @RequestMapping("/poolTest3")
    public VkPublicResponse poolTest3(){
        TcNewSingleThreadExecutor.NoFactoryPool();
        //TcNewSingleThreadExecutor.factoryPool();
        return new VkPublicResponse();
    }

    /**
     * ScheduledExecutorService方法方法测试
     */
    @RequestMapping("/poolTest4")
    public VkPublicResponse poolTest4(){
        //TcNewScheduledThreadPool.schedule();
        //TcNewScheduledThreadPool.scheduleAtFixedRate();
        TcNewScheduledThreadPool.scheduleWithFixedDelay();
        return new VkPublicResponse();
    }


    /**
     * 线程池使用案例  10人抢20件商品
     */
    @RequestMapping("/poolTest5")
    public VkPublicResponse poolTest5(){
        //1.创建一个线程池对象
        //ThreadPoolExecutor executor = new ThreadPoolExecutor(2,3,1, TimeUnit.MINUTES,new LinkedBlockingQueue<>(15));
        //2.循环创建任务对象
        for (int i = 0; i < 20; i++) {
            TcSeckillShop myTask = new TcSeckillShop("我是客户:" + i);
            executor.submit(myTask);
        }
        //3.关闭线程池
        executor.shutdown();
        return new VkPublicResponse();
    }


}